﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Collections.Concurrent;

namespace CodeMonkey.EditableObject.Common
{
    [Obsolete("真的因为反射带来性能问题再考虑")]
    class ReflectionCache
    {
        const BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public;

        //key 为Model的GetType()返回值,,,
        //Value所代表的字典中:key为属性的名称,value为属性的相关信息PropertyInfo
        static IDictionary<Type, IDictionary<string, PropertyInfo>> _typePropertyCache = new ConcurrentDictionary<Type, IDictionary<string, PropertyInfo>>();

        public static IDictionary<string, PropertyInfo> GetPropertyInfoCache(Type type)
        {
            IDictionary<string, PropertyInfo> properties;
            if (_typePropertyCache.TryGetValue(type, out properties))//从缓存池总获取类型包含的属性PropertyInfo集合
            {
                return properties;
            }

            //若缓存池当前没有缓存该类型的属性,,,则提取出相关的属性信息,缓存起来
            properties = CreatePropertyInfoCache(type);
            _typePropertyCache[type] = properties;

            return properties;
        }

        //递归的方式从传入的参数中获取包含的属性,,,先子类,然后向父类递归
        static IDictionary<string, PropertyInfo> CreatePropertyInfoCache(Type type)
        {
            var result = new ConcurrentDictionary<string, PropertyInfo>();

            foreach (PropertyInfo property in type.GetProperties(bindingFlags).Where(p => p.DeclaringType == type)) //只缓存子类自身定义的属性
            {
                result[property.Name] = property;
            }

            if (type.BaseType == null)
            {
                return result;
            }

            foreach (var prop in GetPropertyInfoCache(type.BaseType).Values) //向基类递归,存储相关的属性值
            {
                result[prop.Name] = prop;
            }

            return result;
        }


        public static PropertyInfo GetMatchPropInfo(Type type, string propName)
        {
            return GetPropertyInfoCache(type)[propName];
        }

        public static void CacheTypePropertyInfos(Type type)
        {
            if (_typePropertyCache.ContainsKey(type))
            {
                return;
            }

            IDictionary<string, PropertyInfo> properties = CreatePropertyInfoCache(type);
            _typePropertyCache[type] = properties;
        }
    }
}
